package org.paboo.chart.datamatrix;

import java.io.*;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;

import javax.imageio.ImageIO;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.zxing.common.BitMatrix;
import com.google.zxing.qrcode.encoder.ByteMatrix;
import org.paboo.entity.ImageEntity;
import org.paboo.util.LoggerFactoryUtils;
import org.paboo.util.ParameterObject;
import org.paboo.codec.Base64;
import org.paboo.http.BaseServlet;
import org.paboo.http.HttpMethod;

import com.google.gson.Gson;
import org.paboo.util.ZxingImage;

public class DmServlet extends BaseServlet {

    private static final long serialVersionUID = 3525032759250925015L;
    private LoggerFactoryUtils log = LoggerFactoryUtils.getInstance().load(getClass());

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    protected void processRequest(HttpServletRequest request, HttpServletResponse response, HttpMethod method)
            throws IOException {
        DmEntity e = new DmEntity();
        if (method == HttpMethod.GET) {
            String ctx = getParameterWithDefault(request, "data", ParameterObject.DEFAULT_CONTECT);
            String encoding = StandardCharsets.UTF_8.name();
            ctx = URLDecoder.decode(ctx, encoding);
            ctx = new String(ctx.getBytes(encoding), StandardCharsets.ISO_8859_1);
            e.setData(ctx);

            String format = getParameterWithDefault(request, "format", "png");
            if (format.contains("|")) {
                String[] f = format.split("\\|");
                format = f[0];
                e.setNeedBase64(f[1].toLowerCase().equalsIgnoreCase("base64"));
            } else {
                e.setNeedBase64(false);
            }
            e.setFormat(format);
            String[] size = getParameterWithDefault(request, "size", "128x128").split("x");
            e.setWidth(Integer.valueOf(size[0]));
            e.setHeight(Integer.valueOf(size[1]));
        } else if (method == HttpMethod.POST) {
            BufferedReader br = new BufferedReader(
                    new InputStreamReader(request.getInputStream(), request.getCharacterEncoding()));
            Gson gson = new Gson();
            e = gson.fromJson(br, DmEntity.class);
            if(!ParameterObject.hasText(e.getData())){
                e.setData(ParameterObject.DEFAULT_CONTECT);
            }
            if(!ParameterObject.hasText(e.getFormat())){
                e.setFormat("png");
            }
            if(!ParameterObject.hasInteger(e.getWidth()) || !ParameterObject.hasInteger(e.getWidth())) {
                e.setHeight(128);
                e.setWidth(128);
            }
            if(!ParameterObject.hasBoolean(e.isNeedBase64())){
                e.setNeedBase64(false);
            }
            log.info(gson.toJson(e));
        } else {
            response.sendError(HttpServletResponse.SC_NOT_IMPLEMENTED, "Request error!!!");
            return;
        }

        ByteMatrix matrix = ZxingUtil.encode(e.getData());

        if ("svg".equalsIgnoreCase(e.getFormat())) {
            try {
                response.setContentType("image/svg+xml");
                ZxingImage.toSVGDocument(matrix,
                        new OutputStreamWriter(new BufferedOutputStream(response.getOutputStream()), StandardCharsets.ISO_8859_1.name()),
                        new ImageEntity(e.getHeight(), e.getWidth(), 0, ZxingImage.BLACK, ZxingImage.WHITE));
            } catch (Exception ex) {
                String errorMsg = "Create Fail!!!";
                if (log.isDebugEnabled()) {
                    log.error(errorMsg, ex);
                } else {
                    log.error(errorMsg);
                }
                response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, errorMsg);
            }
            return;
        }

        ImageEntity img = new ImageEntity();
        img.setHeight(e.getHeight());
        img.setMargin(1);
        img.setWidth(e.getWidth());
        img.setFgColor(ZxingImage.BLACK);
        img.setBgColor(ZxingImage.WHITE);

        ByteArrayOutputStream out = new ByteArrayOutputStream();
        if (!ImageIO.write(ZxingImage.toBufferedImage(matrix, img), e.getFormat(), out)) {
            log.error("Could not write an image of format " + e.getFormat());
            throw new IOException("Could not write an image of format " + e.getFormat());
        }
        if (e.isNeedBase64()) {
            String base64 = Base64.encodeToString(out.toByteArray());
            response.setContentType("text/plain");
            response.getOutputStream().print(base64);
        } else {
            response.setContentType("image/" + e.getFormat());
            response.setContentLength(out.size());
            response.getOutputStream().write(out.toByteArray());
        }
    }
}
